.版本 2
.支持库 EThread
.支持库 spec

.程序集 窗口程序集_窗口1
.程序集变量 初始化, 窗口初始化
.程序集变量 客户, Tcp客户端
.程序集变量 连接, 连接
.程序集变量 机器人, 机器人, , "0"
.程序集变量 群缓存, 机器人, , "0"
.程序集变量 许可, 许可
.程序集变量 插件目录, 文本型

.子程序 _窗口1_创建完毕

文件初始化 ()
插件初始化 ()
初始化.窗口初始化 ＝ 真
初始化.窗口代码 ＝ 取随机字母 (5)

启动线程 (&机器人列表初始化, , )
启动线程 (&通讯器自动重连, , )

.子程序 _窗口1_将被销毁


初始化.窗口代码 ＝ “-1”
初始化.窗口初始化 ＝ 假
初始化.机器人初始化 ＝ 假

.如果真 (客户.是否连接中 ())
    客户.断开 ()
    连接.连接状态 ＝ 假
.如果真结束


.子程序 文件初始化
.局部变量 局_软件路径, 文本型


.如果真 (文件是否存在 (取运行目录 () ＋ “\” ＋ “Plugin”) ＝ 假)  ' 用于应用目录判断，不建议删除
    创建目录 (取运行目录 () ＋ “\” ＋ “Plugin”)  ' 用于应用目录创建，不建议删除
.如果真结束
局_软件路径 ＝ 取运行目录 () ＋ “\” ＋ “Plugin\”  ' app的初始目录，一般放在运行目录里面

.如果真 (文件是否存在 (局_软件路径 ＋ “通讯器”) ＝ 假)  ' 用于应用目录判断，不建议删除
    创建目录 (局_软件路径 ＋ “通讯器”)  ' 用于应用目录创建，不建议删除
.如果真结束
插件目录 ＝ 局_软件路径 ＋ “通讯器\”  ' app的初始目录，一般放在运行目录里面



.子程序 插件初始化
.局部变量 str, 文本型


编辑框_端口.内容 ＝ 读配置项 (插件目录 ＋ “配置.ini”, “配置”, “编辑框_端口”, “19730”)
编辑框_IP.内容 ＝ 读配置项 (插件目录 ＋ “配置.ini”, “配置”, “编辑框_IP”, “127.0.0.1”)

连接.IP ＝ 编辑框_IP.内容
连接.端口 ＝ 到整数 (编辑框_端口.内容)


连接.自动重连 ＝ 选择框_自动重连面板.选中
str ＝ 读配置项 (插件目录 ＋ “配置.ini”, “配置”, “选择框_自动重连面板”, )
.判断开始 (str ＝ “真”)
    选择框_自动重连面板.选中 ＝ 真
.判断 (str ＝ “假”)
    选择框_自动重连面板.选中 ＝ 假
.默认

    ' 默认为真
.判断结束

连接.自动重连 ＝ 选择框_自动重连面板.选中

.如果真 (许可.群缓存 ＝ 0)
    许可.群缓存 ＝ 创建进入许可证 ()
.如果真结束
.如果真 (许可.机器人 ＝ 0)
    许可.机器人 ＝ 创建进入许可证 ()
.如果真结束




.子程序 机器人列表初始化
.局部变量 局_窗口代码, 文本型
.局部变量 str, 文本型, , "0"
.局部变量 局_机器人, 机器人
.局部变量 i, 整数型

进入许可区 (许可.机器人)
清除数组 (机器人)
退出许可区 (许可.机器人)

局_窗口代码 ＝ 初始化.窗口代码

str ＝ 分割文本 (Api.取框架QQ号 (0), #换行符, )

.计次循环首 (取数组成员数 (str), i)

    局_机器人.号码 ＝ str [i]
    局_机器人.名字 ＝ 取机器人昵称实时 (str [i])
    局_机器人.在线 ＝ 真

    进入许可区 (许可.机器人)
    加入成员 (机器人, 局_机器人)
    退出许可区 (许可.机器人)

    .如果真 (初始化.窗口初始化 ＝ 假 或 局_窗口代码 ≠ 初始化.窗口代码)
        跳出循环 ()
    .如果真结束

.计次循环尾 ()

.如果真 (局_窗口代码 ＝ 初始化.窗口代码)
    初始化.机器人初始化 ＝ 真  ' 这个变量暂时没什么用

    .如果真 (连接.连接状态)  ' 如果机器人初始化成功后，连接状态是同的，那么就把机器人列表发送到面板里面去
        陈冠希_发送所有账号到面板 (假)
    .如果真结束


.如果真结束




.子程序 通讯器自动重连
.局部变量 i, 整数型
.局部变量 局_窗口代码, 文本型


局_窗口代码 ＝ 初始化.窗口代码

.判断循环首 (初始化.窗口初始化 ＝ 真)

    .如果真 (初始化.机器人初始化 ＝ 真 且 连接.连接状态 ＝ 假 且 连接.自动重连 ＝ 真)
        ' 初始化完了，但是连接状态为假，设置重连
        陈冠希_连接服务器子程序 (假)
    .如果真结束


    .计次循环首 (10, )
        延时 (500)
        .如果真 (局_窗口代码 ≠ 初始化.窗口代码)
            跳出循环 ()
        .如果真结束

    .计次循环尾 ()

    .如果真 (局_窗口代码 ≠ 初始化.窗口代码)
        跳出循环 ()
    .如果真结束

.判断循环尾 ()




.子程序 连接服务器
.局部变量 i, 整数型

.如果 (客户.是否连接中 () ＝ 真)
    客户.断开 ()
    按钮_连接.标题 ＝ “未连接”
    连接.连接状态 ＝ 假
    图片框_连接状态.背景颜色 ＝ #红色

    控件禁止 (假)  ' 解除IP端口禁止

.否则

    .如果真 (连接.端口 ＝ 0)  ' 端口没设置好，直接不重连了
        控件禁止 (假)
        信息框 (“请正确填写连接密码，此密码需要和面板的一样！”, #错误图标, , )
        返回 ()
    .如果真结束

    陈冠希_连接服务器子程序 (真)

.如果结束


.子程序 _按钮_连接_被单击


启动线程 (&连接服务器, , )


.子程序 陈冠希_连接服务器子程序
.参数 连接失败是否弹窗, 逻辑型

.如果真 (初始化.窗口初始化)
    控件禁止 (真)  ' 端口IP禁止
    按钮_连接.禁止 ＝ 真  ' 按钮禁止
.如果真结束

.如果 (客户.连接 (连接.IP, 连接.端口, &客户数据到达, &客户端连接被断开, , 682))
    .如果真 (初始化.窗口初始化)
        按钮_连接.标题 ＝ “已连接”
        连接.连接状态 ＝ 真
        图片框_连接状态.背景颜色 ＝ #绿色

        控件禁止 (真)  ' 端口IP禁止，连接中不能修改IP端口

        .如果真 (初始化.机器人初始化)  ' 如果机器人列表已经初始化成功的话，那就把机器人列表发送过去
            陈冠希_发送所有账号到面板 (假)  ' 重连不需要取名字，只有登录成功的时候才取名字
        .如果真结束

    .如果真结束

.否则

    .如果真 (初始化.窗口初始化)
        控件禁止 (假)  ' 端口IP解除禁止
    .如果真结束

    .如果真 (连接失败是否弹窗)  ' 这个参数决定连接失败后是否弹窗提示，一般手动按钮才需要提示，线程自动重连的话不需要提示
        信息框 (#通讯器连接失败原因, #错误图标, , )
    .如果真结束

.如果结束


.如果真 (初始化.窗口初始化)
    按钮_连接.禁止 ＝ 假  ' 按钮解除禁止
.如果真结束



.子程序 _编辑框_端口_内容被改变

.如果真 (初始化.窗口初始化)
    连接.端口 ＝ 到整数 (编辑框_端口.内容)
    写配置项 (插件目录 ＋ “配置.ini”, “配置”, “编辑框_端口”, 到文本 (连接.端口))
.如果真结束


.子程序 _编辑框_IP_内容被改变

.如果真 (初始化.窗口初始化)
    连接.IP ＝ 编辑框_IP.内容
    写配置项 (插件目录 ＋ “配置.ini”, “配置”, “编辑框_IP”, 编辑框_IP.内容)

.如果真结束


.子程序 陈冠希_发送所有账号到面板
.参数 是否重新取名, 逻辑型
.局部变量 i, 整数型

.计次循环首 (取数组成员数 (机器人), i)
    .如果真 (机器人 [i].在线)
        .如果 (是否重新取名)
            消息事件处理 (机器人 [i].号码, #熊猫群聊_QQ登录完成, 机器人 [i].名字, “”, “”)  ' 这里是刚刚登陆完成的QQ，所以重新取一次名字吧

        .否则

            消息事件处理 (机器人 [i].号码, #熊猫群聊_QQ登录完成, 机器人 [i].名字, “-1”, “-1”)  ' 这里是刚初始化机器人的，刚才取好名字，所以不需要取名字，最后两个参数写入-1就好
        .如果结束

    .如果真结束

.计次循环尾 ()


.子程序 控件禁止
.参数 禁止, 逻辑型


编辑框_端口.禁止 ＝ 禁止
编辑框_IP.禁止 ＝ 禁止


.子程序 客户数据到达, 整数型
.参数 客户端id, 整数型
.参数 连接id, 整数型
.参数 pdata, 整数型
.参数 len, 整数型
.局部变量 数据, 字节集
.局部变量 取回数据, 文本型
.局部变量 str, 文本型, , "0"
.局部变量 局_机器人QQ, 文本型
.局部变量 i, 整数型
.局部变量 txt, 文本型


数据 ＝ 指针到字节集 (pdata, len)
' 数据 ＝ 解密数据 (数据, 解密密码, #RC4算法)

取回数据 ＝ 到文本 (数据)
str ＝ 分割文本 (取回数据, “→←”, )
.如果真 (取数组成员数 (str) ＜ 2)
    返回 (0)
.如果真结束


.判断开始 (str [1] ＝ “102” 且 取数组成员数 (str) ≥ 4)  ' 被加好友

    ' 102→←机器人→←添加人→←添加附言

    Api.置好友验证事件 (str [2], str [3], 10, “”)

.判断 (str [1] ＝ “103” 且 取数组成员数 (str) ≥ 5)  ' 被邀请进群

    ' 103→←机器人→←添加群→←添加人→←seq
    Api.同意邀请入群请求 (str [2], str [5])


.判断 (str [1] ＝ “2” 且 取数组成员数 (str) ≥ 5)

    ' 2→←机器人→←参_消息来源→←参_消息内容→←气泡→←
    Api.发送消息 (str [2], 2, str [3], str [3], str [4], 到整数 (str [5]), 0, 0)

.判断 (str [1] ＝ “9” 且 取数组成员数 (str) ≥ 3)

    ' “9→←” ＋ 局_机器人QQ ＋ “→←” ＋ 参_消息来源 ＋ “→←”
    Api.退群 (str [2], str [3])


.判断 (str [1] ＝ “99” 且 取数组成员数 (str) ≥ 3)
    ' “99→←” ＋ 局_机器人QQ ＋ “→←” ＋ 123|456|789|111 ＋ “→←”
    执行退非工作群 (str [2], str [3])

.判断 (str [1] ＝ “105” 且 取数组成员数 (str) ≥ 4)  ' 申请添加好友
    ' 105→←机器人→←添加人→←答案→←
    Api_AddFriend (str [2], str [3], “”)

.判断 (str [1] ＝ “106” 且 取数组成员数 (str) ≥ 4)  ' 申请添加群
    ' 106→←机器人→←添加群→←答案→←
    Api_JoinGroup (str [2], str [3], “”)

.判断 (str [1] ＝ “201” 且 取数组成员数 (str) ≥ 2)  ' 刷新QQ名字
    ' 201→←机器人→←

    .计次循环首 (取数组成员数 (机器人), i)
        .如果真 (机器人 [i].号码 ＝ str [2] 且 机器人 [i].在线 ＝ 真)

            txt ＝ 取机器人昵称实时 (机器人 [i].号码)

            .如果真 (txt ≠ “”)
                机器人 [i].名字 ＝ txt
            .如果真结束

            跳出循环 ()
        .如果真结束

    .计次循环尾 ()


    .如果真 (txt ≠ “”)
        客户.发送数据 (到字节集 (“201→←” ＋ str [2] ＋ “→←” ＋ txt ＋ “→←”))
    .如果真结束

.默认

.判断结束

返回 (0)


.子程序 执行退非工作群
.参数 局_机器人QQ, 文本型
.参数 局_群号码, 文本型
.局部变量 局_不退群号码, 文本型, , "0"
.局部变量 局_加入的群, 文本型, , "0"
.局部变量 i, 整数型
.局部变量 a, 整数型
.局部变量 找到, 逻辑型


局_加入的群 ＝ 分割文本 (Api_GetGroupList_A (局_机器人QQ), #换行符, )
局_不退群号码 ＝ 分割文本 (局_群号码, “|”, )

.计次循环首 (取数组成员数 (局_加入的群), i)
    找到 ＝ 假
    .计次循环首 (取数组成员数 (局_不退群号码), a)
        .如果真 (局_不退群号码 [a] ＝ 局_加入的群 [i])
            找到 ＝ 真  ' 找到群号，表示这个群是工作群，不退
            跳出循环 ()
        .如果真结束

    .计次循环尾 ()

    .如果真 (找到 ＝ 假)  ' 没找到群号
        Api_QuitGroup (局_机器人QQ, 局_加入的群 [i])
    .如果真结束

.计次循环尾 ()




.子程序 客户端连接被断开, 整数型
.参数 客户端id, 整数型
.参数 连接id, 整数型
.参数 op, 整数型
.参数 errcode, 整数型

.如果 (errcode ＝ 0)
    ' 调试输出 (“正常断开”)
.否则

.如果结束

连接.连接状态 ＝ 假

.如果真 (初始化.窗口初始化)
    按钮_连接.标题 ＝ “未连接”
    图片框_连接状态.背景颜色 ＝ #红色
    控件禁止 (假)

.如果真结束

返回 (0)


.子程序 消息事件处理
.参数 参_机器人QQ, 文本型, , 用于区分是框架里哪个QQ接收到该消息
.参数 参_消息或事件类型, 整数型, , #消息类型_  或  #事件_  开头常量
.参数 参_消息来源, 文本型, , 一般为 群号 或 好友QQ 其他情况自行打印查看
.参数 参_触发对象_主动, 文本型
.参数 参_消息内容, 文本型, , 一般为：对方发送的消息内容。 其他情况自行打印查看


' 群消息=2 登陆=100 101=离线 102=被加 103=被邀群

.如果真 (初始化.窗口初始化)
    .如果真 (参_消息或事件类型 ＝ #熊猫群聊_QQ离线)
        机器人进缓存 (参_机器人QQ, 假)  ' 刷新离线
    .如果真结束
    .如果真 (参_消息或事件类型 ＝ #熊猫群聊_QQ登录完成)
        ' 这里QQ登陆完成传到面板后，面板会判断是否存在此号码，不存在的话就加入此号码到机器人数组
        ' ---------------------------查看号码是否存在缓存中，存在就刷新名字，不存在就加入--------------------------------------------

        .如果真 (参_触发对象_主动 ≠ “-1” 或 参_消息内容 ≠ “-1”)  ' 机器人列表初始化的话这两个参数都为-1，因为初始化是刚取名字，无需再重复这个步骤
            机器人进缓存 (参_机器人QQ, 真)  ' 刷新在线
        .如果真结束

    .如果真结束

    .如果真 (连接.连接状态)
        .判断开始 (参_消息或事件类型 ＝ #熊猫群聊_群消息事件)
            ' 2→←机器人→←消息来源→←发信人→←消息内容→←机器人昵称→←群昵称

            客户.发送数据 (到字节集 (“2→←” ＋ 参_机器人QQ ＋ “→←” ＋ 参_消息来源 ＋ “→←” ＋ 参_触发对象_主动 ＋ “→←” ＋ 参_消息内容 ＋ “→←” ＋ 取机器人名字缓存 (参_机器人QQ) ＋ “→←” ＋ 取群名字缓存 (参_机器人QQ, 参_消息来源) ＋ “→←”))

        .判断 (参_消息或事件类型 ＝ #熊猫群聊_QQ登录完成)
            ' 100→←机器人→←昵称

            ' ----------------------------------------------------------------------------------------------------------------------------
            客户.发送数据 (到字节集 (“100→←” ＋ 参_机器人QQ ＋ “|QQ→←” ＋ 取机器人名字缓存 (参_机器人QQ) ＋ “→←”))

        .判断 (参_消息或事件类型 ＝ #熊猫群聊_QQ离线)
            ' 101→←机器人

            客户.发送数据 (到字节集 (“101→←” ＋ 参_机器人QQ ＋ “→←”))

        .判断 (参_消息或事件类型 ＝ #熊猫群聊_被添加好友)
            ' 102→←机器人→←添加人→←添加附言→←

            客户.发送数据 (到字节集 (“102→←” ＋ 参_机器人QQ ＋ “→←” ＋ 参_触发对象_主动 ＋ “→←” ＋ 参_消息内容 ＋ “→←”))

        .判断 (参_消息或事件类型 ＝ #熊猫群聊_我被邀请加入群)
            ' 103→←机器人→←添加群→←添加人→←seq
            客户.发送数据 (到字节集 (“103→←” ＋ 参_机器人QQ ＋ “→←” ＋ 参_消息来源 ＋ “→←” ＋ 参_触发对象_主动 ＋ “→←” ＋ 参_消息内容 ＋ “→←”))

        .默认

        .判断结束

    .如果真结束

.如果真结束


.子程序 机器人进缓存
.参数 参_机器人QQ, 文本型
.参数 参_在线, 逻辑型
.局部变量 i, 整数型
.局部变量 找到, 逻辑型
.局部变量 局_机器人, 机器人


进入许可区 (许可.机器人)
.计次循环首 (取数组成员数 (机器人), i)
    .如果真 (机器人 [i].号码 ＝ 参_机器人QQ)
        机器人 [i].在线 ＝ 参_在线
        .如果真 (参_在线)
            机器人 [i].名字 ＝ 取机器人昵称实时 (参_机器人QQ)  ' 刷新QQ名字
        .如果真结束

        找到 ＝ 真
        跳出循环 ()
    .如果真结束

.计次循环尾 ()

.如果真 (找到 ＝ 假)
    局_机器人.号码 ＝ 参_机器人QQ
    局_机器人.名字 ＝ 取机器人昵称实时 (参_机器人QQ)
    局_机器人.在线 ＝ 真
    加入成员 (机器人, 局_机器人)
.如果真结束

退出许可区 (许可.机器人)


.子程序 取机器人昵称实时, 文本型
.参数 参_机器人, 文本型
.局部变量 str, 文本型

str ＝ Api_GetNick (参_机器人, 参_机器人)
.如果真 (str ＝ “”)
    str ＝ Api_GetNick (参_机器人, 参_机器人)
.如果真结束

返回 (str)

.子程序 取机器人名字缓存, 文本型
.参数 参_机器人QQ, 文本型
.局部变量 i, 整数型
.局部变量 str, 文本型


.计次循环首 (取数组成员数 (机器人), i)
    .如果真 (机器人 [i].号码 ＝ 参_机器人QQ)
        .如果真 (机器人 [i].名字 ＝ “”)  ' 缓存列表的QQ名字是空的，那么就再取两次’一般情况下来说因该不会空
            str ＝ 取机器人昵称实时 (参_机器人QQ)
        .如果真结束

        .如果真 (str ≠ “”)
            机器人 [i].名字 ＝ str
        .如果真结束

        返回 (机器人 [i].名字)
    .如果真结束

.计次循环尾 ()
返回 (“”)


.子程序 取群名字缓存, 文本型
.参数 参_机器人, 文本型
.参数 参_群号码, 文本型
.局部变量 i, 整数型
.局部变量 str, 文本型
.局部变量 局_群缓存, 机器人


进入许可区 (许可.群缓存)

.计次循环首 (取数组成员数 (群缓存), i)
    .如果真 (群缓存 [i].号码 ＝ 参_群号码)
        str ＝ 群缓存 [i].名字
        跳出循环 ()
    .如果真结束

.计次循环尾 ()

.如果真 (str ＝ “”)
    str ＝ Api_GetGroupName (参_机器人, 参_群号码)
    .如果真 (str ≠ “”)
        局_群缓存.号码 ＝ 参_群号码
        局_群缓存.名字 ＝ str
        加入成员 (群缓存, 局_群缓存)
    .如果真结束

.如果真结束

退出许可区 (许可.群缓存)

返回 (str)


.子程序 取随机字母, 文本型
.参数 数量, 整数型
.局部变量 字母, 文本型, , "0"
.局部变量 txt, 文本型



' 默认大小写字母拼凑

字母 ＝ { “a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “i”, “j”, “k”, “l”, “m”, “n”, “o”, “p”, “q”, “r”, “s”, “t”, “u”, “v”, “w”, “x”, “y”, “z”, “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”, “J”, “K”, “L”, “M”, “N”, “O”, “P”, “Q”, “R”, “S”, “T”, “U”, “V”, “W”, “X”, “Y”, “Z” }


.计次循环首 (数量, )
    txt ＝ txt ＋ 字母 [MT_Rand (1, 52)]
.计次循环尾 ()

返回 (txt)

.子程序 MT_Rand, 整数型, , 高质量伪随机数，不需要【置随机数种子】
.参数 min, 整数型, , 可为负数
.参数 max, 整数型, , 可为负数
.局部变量 _g_p, 整数型, 静态
.局部变量 p, 整数型

.如果真 (_g_p ＝ 0)
    _g_p ＝ 申请内存 (2504, 真)
    .如果真 (_g_p ＝ 0)
        返回 (min)
    .如果真结束

.如果真结束
p ＝ _g_p
置入代码 ({ 96, 131, 120, 8, 0, 15, 132, 224, 0, 0, 0, 185, 1, 0, 0, 0, 246, 64, 4, 1, 117, 250, 135, 72, 4, 133, 201, 117, 243, 129, 56, 112, 2, 0, 0, 116, 91, 139, 16, 255, 0, 139, 76, 144, 8, 199, 64, 4, 0, 0, 0, 0, 137, 200, 193, 233, 11, 49, 193, 137, 200, 37, 173, 88, 58, 255, 193, 224, 7, 49, 193, 137, 200, 37, 140, 223, 255, 255, 193, 224, 15, 49, 193, 137, 200, 193, 232, 18, 49, 200, 139, 77, 12, 139, 93, 8, 57, 217, 124, 20, 41, 217, 65, 49, 210, 247, 241, 137, 208, 1, 216, 137, 68, 36, 28, 97, 201, 194, 8, 0, 139, 77, 8, 139, 93, 12, 235, 228, 49, 246, 139, 125, 252, 87, 85, 131, 199, 8, 137, 253, 187, 141, 1, 0, 0, 70, 137, 242, 49, 192, 129, 254, 112, 2, 0, 0, 15, 68, 208, 139, 84, 149, 0, 51, 23, 129, 226, 255, 255, 255, 127, 51, 23, 137, 208, 209, 232, 137, 193, 129, 241, 223, 176, 8, 153, 128, 226, 1, 15, 68, 200, 49, 210, 129, 251, 112, 2, 0, 0, 15, 68, 218, 137, 218, 51, 76, 149, 0, 137, 15, 141, 127, 4, 67, 129, 251, 141, 1, 0, 0, 117, 179, 93, 88, 199, 0, 0, 0, 0, 0, 233, 58, 255, 255, 255, 100, 139, 13, 32, 0, 0, 0, 100, 161, 44, 0, 0, 0, 100, 15, 175, 13, 36, 0, 0, 0, 131, 209, 0, 100, 51, 5, 48, 0, 0, 0, 51, 77, 252, 247, 225, 17, 194, 139, 93, 252, 131, 195, 8, 137, 19, 49, 192, 137, 209, 193, 233, 30, 49, 209, 105, 209, 101, 137, 7, 108, 64, 1, 194, 137, 20, 131, 61, 111, 2, 0, 0, 114, 230, 233, 70, 255, 255, 255 })
返回 (0)

.子程序 _选择框_自动重连面板_被单击

.如果真 (初始化.窗口初始化)
    连接.自动重连 ＝ 选择框_自动重连面板.选中
    写配置项 (插件目录 ＋ “配置.ini”, “配置”, “选择框_自动重连面板”, 到文本 (连接.自动重连))
.如果真结束


